package com.qxt.prize.repositories;

import com.qxt.prize.forms.PrizeForm;
import com.qxt.prize.mappers.PrizeMapper;
import com.qxt.prize.models.Prize;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.apache.commons.lang3.StringUtils;
import org.intellij.lang.annotations.Language;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import top.moirae.core.AbstractOption;
import top.moirae.jdbc.MysqlJDBCSupport;
import top.moirae.repository.PaginationData;
import top.moirae.repository.PaginationForm;

import java.time.LocalDateTime;

@Named
public class PrizeRepository extends MysqlJDBCSupport {
    @Inject
    protected PrizeRepository(@Named("BUSINESS_DB") JdbcTemplate db, @Named("BUSINESS_NAMED_DB") NamedParameterJdbcTemplate namedDB) {
        super(db, namedDB);
    }

    @Language("SQL")
    final String column = """
            select p.`id`,
                   p.`name`,
                   p.`value`,
                   p.`description`,
                   p.`quantity`,
                   p.`publish_at`,
                   p.`type`,
                   p.`cover`,
                   p.`create_at`,
                   p.`create_by`,
                   u.name as create_by_name
            from `prize` p
                     left join user u on u.id = p.create_by
            where 1 = 1  
            """;

    public AbstractOption<Prize> option(long id) {
        @Language("SQL") String sql = column + " AND p.id = :id ";
        MapSqlParameterSource params = new MapSqlParameterSource("id", id);
        return option(sql, PrizeMapper.DETAIL, params);
    }

    public int delete(long id) {
        @Language("SQL") String sql = "delete from `prize` where id = :id";
        MapSqlParameterSource params = new MapSqlParameterSource("id", id);
        return update(sql, params);
    }

    public long create(long optUserId, PrizeForm.Create form) {
        @Language("SQL") String sql = "insert into `prize`(`name`,`value`,`quantity`,`description`,`type`,`cover`,`create_at`,`create_by`) values (:name,:value,:quantity,:description,:type,:cover,:createAt,:createBy)";
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("name", form.getName());
        params.addValue("value", form.getValue());
        params.addValue("quantity", form.getQuantity().orNull());
        params.addValue("description", form.getDescription().orNull());
        params.addValue("type", form.getType().name());
        params.addValue("cover", form.getCover());
        params.addValue("createAt", LocalDateTime.now());
        params.addValue("createBy", optUserId);
        return update(sql, params);
    }

    public long update(long optUserId, long id, PrizeForm.Update form) {
        @Language("SQL") String sql = "update `prize` set `name`=:name,`value`=:value,`quantity`=:quantity,`description`=:description,`publish_at`=:publishAt,`type`=:type,`cover`=:cover where id=:id";
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        params.addValue("name", form.getName());
        params.addValue("value", form.getValue());
        params.addValue("description", form.getDescription().orNull());
        params.addValue("quantity", form.getQuantity().orNull());
        params.addValue("publishAt", form.getPublishAt().orNull());
        params.addValue("type", form.getType().name());
        params.addValue("cover", form.getCover());
        return update(sql, params);
    }


    public long changePublishStateOn(long id) {
        @Language("SQL") String sql = "update `prize` set `publish_at`=:publishAt where id=:id";
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        params.addValue("publishAt", LocalDateTime.now());
        return update(sql, params);
    }

    public long changePublishStateOff(long id) {
        @Language("SQL") String sql = "update `prize` set `publish_at`=:publishAt where id=:id";
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        params.addValue("publishAt", null);
        return update(sql, params);
    }

    public long minusInventory(long id, long quantity) {
        @Language("SQL") String sql = "update `prize` set `quantity`=:quantity where id=:id";
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        params.addValue("quantity", quantity);
        return update(sql, params);
    }

    public boolean isExits(long id) {
        @Language("SQL") String sql = "select COUNT(0) from `prize` where id=:id";
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        return object(sql, Long.class, params) > 0;
    }

    public PaginationData<Prize> list(PrizeForm.Search form, PaginationForm paginationForm) {
        @Language("SQL") String sql = column;
        MapSqlParameterSource params = new MapSqlParameterSource();
        sql += form.getName().map(name -> {
            params.addValue("name", like(name));
            return " and p.name like :name ";
        }).getOrElse(StringUtils.EMPTY);

        sql += form.getType().map(type -> {
            params.addValue("type", type);
            return " and p.type = :type ";
        }).getOrElse(StringUtils.EMPTY);

        sql += form.isPublish().map(isPublish-> {
            if (isPublish) {
                return " and p.publish_at is not null ";
            }else {
                return " and p.publish_at is null ";
            }
        }).getOrElse(StringUtils.EMPTY);

        return paged(sql, PrizeMapper.DETAIL, params, paginationForm);
    }
}

